#ifndef __COMMBASE_H__
#define __COMMBASE_H__

#include "plat/nonecopyable.h"
#include "commdef.h"
#include "os/msgqueue.h"
#include "os/thread.h"
#include "os/mutex.h"
#include <list>

#define COMM_THREAD_STACK_SIZE (256*4)
#define COMM_RECV_BYTE_BUFFER_MAX 256

/// @brief 通信基类
class CommBase : public NoneCopyable
{
    using RespReceivedCallback = std::function<void(std::shared_ptr<IProtocolMessage>)>;

public:
    explicit CommBase();
    virtual ~CommBase();

public:
    void SetRespReceivedCallback(const RespReceivedCallback &callback);
    
    void Start();
    void Stop();
    
    void Send(std::shared_ptr<IProtocolMessage> msg);
    std::shared_ptr<IProtocolMessage> SendWait(std::shared_ptr<IProtocolMessage> msg, int timeout = COMM_WAIT_TIMEOUT_DEFAULT);

protected:
    void RecvByte(int c);
    void ConfigBase(IProtocol *protocol);

protected:
    virtual void OnRespReceived(std::shared_ptr<IProtocolMessage> msg);
    virtual void OnWriteStream(uint8_t *data, int dataLen) = 0;

private:
    //在线程中执行
    void Loop();
    void HandleMessage(std::shared_ptr<IProtocolMessage> msg);

private:
    std::shared_ptr<IProtocolMessage> SendImpl(std::shared_ptr<IProtocolMessage> msg, bool wait, int timeout);   
    std::shared_ptr<WaitObject> WriteStreamImpl(std::shared_ptr<IProtocolMessage> msg, bool wait, int timeout);

protected:
    IProtocol *m_protocol = nullptr;
    
    Thread m_thread{COMM_THREAD_STACK_SIZE};
    MsgQueue<char, COMM_RECV_BYTE_BUFFER_MAX> m_recvQ;

    //
    Mutex m_sendMutex;
    Mutex m_waitListMutex;
    std::list<std::shared_ptr<WaitObject>> m_waitList;

    RespReceivedCallback m_respCallback = nullptr;
};

#endif // __COMMBASE_H__
